#ifndef __DATETIME_H__
#define __DATETIME_H__

#include <cstdint>
#include <string>
#include <chrono>
#include <ratio>
#include <memory>

namespace wb {

/**
 * @brief 把chrono库的内容进一步包装，简化操作提供简单的公有接口
 * chrono库的核心三要素：duration时间段类型，单位为秒
 *                    time_point时间点类型，表示一个确切的时间
 *                    clock时钟类型，通常获取当前的系统时钟，可以转换成time_t
 */
class Date
{
using sys_clock         = std::chrono::system_clock;
using sys_timepoint     = sys_clock::time_point;
using days_dur          = std::chrono::duration<int, std::ratio<24*60*60, 1>>;
using days_timepoint    = std::chrono::time_point<sys_clock, days_dur>;
using seconds_dur       = std::chrono::seconds;
using millis_dur        = std::chrono::milliseconds;
using micros_dur        = std::chrono::microseconds;
using minutes_dur       = std::chrono::minutes;
using hours_dur         = std::chrono::hours;

public: //构造析构
    /**
     * @brief 默认构造，取当前时间的系统时间点，并记录当前天数
     *
     */
    Date() {
        m_timepoint = sys_clock::now();
        m_dayspoint = std::chrono::time_point_cast<days_dur>(sys_clock::now());
    }

    /**
     * @brief 转换构造，将系统时钟时间点转换成天数，构造Date类型
     *
     * @param systp
     */
    Date(const sys_timepoint& systp): m_timepoint(systp) {
        m_dayspoint = std::chrono::time_point_cast<days_dur>(systp);
    }

    /**
     * @brief 转换构造，将按日存储的时间，即天数，转换成系统时钟对应的时间点，并构造Date类型
     *
     * @param days
     */
    Date(const days_timepoint& days): m_dayspoint(days) {
        m_timepoint = std::chrono::time_point_cast<sys_clock::duration>(days);
    }
    ~Date() = default;

public: //公有接口
    /**
     * @brief 返回表示当前时间的Date类型常量，静态方法
     * @return const Date
     */
    static const Date datetime();
    /**
     * @brief Date::datetime()的别名，静态方法
     * @return const Date
     */
    static const Date now() { return Date::datetime();}

    /**
     * @brief 返回表示当前日期的Date类型常量，时，分，秒均置为0
     * @return const Date
     */
    const Date today() const ;

    /**
     * @brief 返回当前时刻+1天后的Date类型常量
     * @return const Date
     */
    const Date tomorrow() const;

    /**
     * @brief  获得int64_t秒后的Date类型
     * @param  sec int64_t表示的秒数
     * @return const Date
     */
    const Date secondsLater(int64_t sec) const;

    /**
     * @brief 返回64位整型时间戳
     * @return int64_t
     */
    int64_t microSecondSinceEpoch() const;
    /**
     * @brief 返回tm时间结构体
     * @return struct tm
     */
    std::shared_ptr<struct tm> tmStruct() const;
    //struct tm tmStruct() const;

    /**
     * @brief 返回当前本地时间string字符串，自带换行
     * @return std::string
     */
    std::string toString() const;
    /**
     * @brief 按照fmtstr格式返回当前本地时间string字符串
     * @param  fmtstr 字符串常量，若为null，调用字符
     * @return std::string
     */
    std::string toString(const char* fmtstr) const;
    /**
     * @brief 返回时间戳字符串
     * @return std::string
     */
    std::string timeStamp() const;

public: //运算符重载

private:
    sys_timepoint m_timepoint; //当前系统时钟的精确时间
    days_timepoint m_dayspoint; //按天计算当距epoch的天数
};



}


#endif // __DATETIME_H__